extends PlayerMoveComponentBase
class_name PlayerHorizontalMoveInCurveComponent

@export_group("跳跃")
@export var jump_power:float = 258
##角色从地面开始起跳到落地过程中的最大跳跃次数(包括起跳跳跃动作)
@export var max_jump_count:int = 1:
	set(value):
		max_jump_count = value
		current_jump_count = min(max_jump_count,current_jump_count)
##当前剩余的角色可跳跃次数
@export var current_jump_count:int = 1:
	set(value):
		current_jump_count = clamp(value,0,max_jump_count)
@export_subgroup("狼跳")
##从离开地面开始可进行狼跳的时间
@export var empty_jump_time:float = 0.5
var empty_jump_timer:Timer
@export_subgroup("空中移动速度偏移","air")
##由跳跃键和下蹲键引起空中竖直轴速度偏移
@export var air_velocity_y_offset_by_input:float = 4
##因角色身处空中产生的水平移动的速度乘区
@export var air_velocity_x_multiplication:float = 0.8
@export_subgroup("跳跃提前输入容错")
##玩家在角色从空中按下跳跃键后如果在advance_input_jump_timej时间内落地，会立即起跳
@export var advance_input_jump_time:float = 0.2
var advance_input_jump_timer:Timer
@export_group("加速")
@export var time_faster:float = 0.3
@export var faster_curve:Curve
var faster_progress:float = 0:
	set(value):
		faster_progress = clamp(value,0,1)

@export_group("减速")
##当速度方向与加速度方向相反时，减速时间会少于设置时间
@export var time_slower:float = 0.2
@export var slower_curve:Curve
var slower_progress:float = 0:
	set(value):
		slower_progress = clamp(value,0,1)

enum MoveState{
	Ground,
	Air}

var current_MoveState:MoveState

func _ready() -> void:
	empty_jump_timer = _create_timer(empty_jump_time)
	advance_input_jump_timer = _create_timer(advance_input_jump_time)

func _move(delta: float):
	_update_movestate()
	_set_mover_velocity_x(delta)
	_set_mover_veloctiy_y()
	_check_external_setted_velocity()

func _update_movestate():
	if mover.is_on_floor():
		if current_MoveState == MoveState.Ground:
			return
		current_MoveState = MoveState.Ground
		
		current_jump_count = max_jump_count
		empty_jump_timer.stop()
	else:
		if current_MoveState == MoveState.Air:
			return
		current_MoveState = MoveState.Air
		
		if empty_jump_timer.is_stopped() and mover.velocity.y > 0:
			empty_jump_timer.start()
			await empty_jump_timer.timeout
			current_jump_count -= 1

#region x轴水平移动
func _set_mover_velocity_x(delta:float):
	if input_dir.x == 0 and mover.velocity.x != 0:
		_deceleration(delta)
	elif input_dir.x == - mover.velocity.x:
		_deceleration(delta)
	elif input_dir.x != 0:
		_accelerate(delta)

func _accelerate(delta:float):
	faster_progress += delta / time_faster
	slower_progress -= delta / time_faster
	var curve_value = faster_curve.sample(faster_progress)
	
	mover.velocity.x = max_speed * curve_value * input_dir.x
	
	if !mover.is_on_floor() and input_dir.x != 0:
		mover.velocity.x *= air_velocity_x_multiplication

func _deceleration(delta:float):
	faster_progress -= delta / time_faster
	slower_progress += delta / time_faster
	var curve_value = slower_curve.sample(slower_progress)
	var mover_velocity_x:float = mover.velocity.normalized().x
	
	if input_dir.x == 0:
		mover.velocity.x = max_speed * curve_value * input_dir.x
	else:
		mover.velocity.x = max_speed * curve_value * lerpf(mover_velocity_x,input_dir.x,slower_progress)
	
	if !mover.is_on_floor() and input_dir.x != 0:
		mover.velocity.x *= air_velocity_x_multiplication
#endregion

#region y轴竖直运动
func _set_mover_veloctiy_y():
	if mover.is_on_floor():
		mover.velocity.y = 0
	else:
		mover.velocity.y += gravity + input_dir.y * air_velocity_y_offset_by_input
	
	_check_advanced_jump_input()
	
	if current_jump_count > 0 and input_dir.y < 0:
		mover.velocity.y = -jump_power 
		current_jump_count -= 1
	elif mover.is_on_floor() and !advance_input_jump_timer.is_stopped():
		mover.velocity.y = -jump_power 
		current_jump_count -= 1
		advance_input_jump_timer.stop()

func _check_advanced_jump_input():
	if !mover.is_on_floor() and Input.is_action_just_pressed(up_action):
		if advance_input_jump_timer.is_stopped():
			advance_input_jump_timer.start()
#endregion

func _create_timer(time:float)->Timer:
	var timer = Timer.new()
	timer.one_shot = true
	timer.wait_time = time
	add_child(timer)
	return timer
